package service

import (
	"context"
	"errors"
	"time"
	"wx-uniapp-go/internal/repository/dto"
	"wx-uniapp-go/internal/repository/models"
)

// RedPacketService 红包服务接口
type RedPacketService interface {
	// GetAccount 获取红包账户信息
	GetAccount(ctx context.Context, userId int64) (*dto.RedPacketAccountResp, error)

	// ListRecords 获取红包流水记录列表
	ListRecords(ctx context.Context, userId int64, req *dto.ListRedPacketRecordReq) (*dto.ListRedPacketRecordResp, error)

	// UseRedPacket 使用红包
	UseRedPacket(ctx context.Context, userId int64, req *dto.UseRedPacketReq) error

	// RefundRedPacket 退回红包
	RefundRedPacket(ctx context.Context, userId int64, req *dto.RefundRedPacketReq) error

	// SendRedPacket 发放红包
	SendRedPacket(ctx context.Context, req *dto.SendRedPacketReq) (*dto.SendRedPacketResp, error)
}

// redPacketService 红包服务实现
type redPacketService struct {
}

// NewRedPacketService 创建红包服务实例
func NewRedPacketService() RedPacketService {
	return &redPacketService{}
}

// GetAccount 获取红包账户信息
func (s *redPacketService) GetAccount(ctx context.Context, userId int64) (*dto.RedPacketAccountResp, error) {
	account, err := models.GetRedPacketAccount(ctx, userId)
	if err != nil {
		return nil, err
	}

	return &dto.RedPacketAccountResp{
		Balance:      account.Balance,
		TotalIncome:  account.TotalIncome,
		TotalExpense: account.TotalExpense,
	}, nil
}

// ListRecords 获取红包流水记录列表
func (s *redPacketService) ListRecords(ctx context.Context, userId int64, req *dto.ListRedPacketRecordReq) (*dto.ListRedPacketRecordResp, error) {
	records, total, err := models.GetRedPacketRecords(ctx, userId, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	list := make([]dto.RedPacketRecordItem, 0, len(records))
	for _, record := range records {
		list = append(list, dto.RedPacketRecordItem{
			Id:         record.Id,
			Type:       record.Type,
			Amount:     record.Amount,
			Balance:    record.Balance,
			Source:     record.Source,
			Title:      record.Title,
			Remark:     record.Remark,
			Status:     record.Status,
			ExpireTime: record.ExpireTime.Format(time.DateTime) + "到期",
			CreateTime: record.CreateTime.Format(time.DateTime),
		})
	}

	return &dto.ListRedPacketRecordResp{
		Total:    total,
		List:     list,
		Page:     req.Page,
		PageSize: req.PageSize,
	}, nil
}

// UseRedPacket 使用红包
func (s *redPacketService) UseRedPacket(ctx context.Context, userId int64, req *dto.UseRedPacketReq) error {
	record := &models.RedPacketRecord{
		UserId:   userId,
		Type:     models.RedPacketTypeExpense,
		Amount:   req.Amount,
		Source:   req.Source,
		SourceId: "",
		Title:    req.Title,
		Remark:   req.Remark,
		Status:   models.RedPacketStatusNormal,
	}
	return models.CreateRedPacketRecord(ctx, record)
}

// RefundRedPacket 退回红包
func (s *redPacketService) RefundRedPacket(ctx context.Context, userId int64, req *dto.RefundRedPacketReq) error {
	return models.RefundRedPacketRecord(ctx, req.RecordId)
}

// SendRedPacket 发放红包
func (s *redPacketService) SendRedPacket(ctx context.Context, req *dto.SendRedPacketReq) (*dto.SendRedPacketResp, error) {
	// 获取红包规则
	rule, err := models.GetRedPacketRule(ctx, req.Source)
	if err != nil {
		return nil, err
	}
	if rule == nil {
		return nil, errors.New("红包规则不存在")
	}

	// 检查用户领取限制
	allowed, err := rule.CheckUserLimit(ctx, req.UserId)
	if err != nil {
		return nil, err
	}
	if !allowed {
		return nil, errors.New("超出领取限制")
	}

	// 计算红包金额
	amount := rule.CalculateAmount(req.BaseAmount)
	if amount <= 0 {
		return nil, errors.New("红包金额无效")
	}

	// 创建红包记录
	record := &models.RedPacketRecord{
		UserId:   req.UserId,
		Type:     models.RedPacketTypeIncome,
		Amount:   amount,
		Source:   req.Source,
		SourceId: "",
		Title:    req.Title,
		Remark:   req.Remark,
		Status:   models.RedPacketStatusNormal,
	}

	// 设置过期时间
	if req.ValidDays > 0 {
		record.ExpireTime = time.Now().AddDate(0, 0, req.ValidDays)
	} else if rule.ValidDays > 0 {
		record.ExpireTime = time.Now().AddDate(0, 0, rule.ValidDays)
	}

	if err := models.CreateRedPacketRecord(ctx, record); err != nil {
		return nil, err
	}

	return &dto.SendRedPacketResp{
		Amount: amount,
	}, nil
}
